<?php
/**
 * @package    gadgets
 * @subpackage feature
 * @author     Daniel Botelho <botelho.daniel@gmail.com>
 */
class GadgetsTabSet implements Instanciatable 
{
  const ALIGN_LEFT = "'left'";
  const ALIGN_RIGHT = "'right'";
  const ALIGN_CENTER = "'center'";
  
  private $var;
  private $initizalized;
  private $opt_moduleId;
  private $opt_defaultTab;
  private $opt_container;
  
  public function __construct($var, $div=null)
  {
    $this->var = $var;
    if($div) $this->opt_container = "document.getElementById('$div')";
    $this->initizalized = false;
  }
  
  public function setOptModuleId($opt_moduleId)
  {
    $this->opt_moduleId = $opt_moduleId;
  }
  public function setOptDefaultTab($opt_defaultTab)
  {
    $this->opt_defaultTab = $opt_defaultTab;
  }
  public function setOptContainer($opt_container)
  {
    $this->opt_container = $opt_container;
  }
  
  public function getVarName()
  {
    return $this->var;
  }
  
  /**
   * This method will only initialize the variable used by this TabSet. This method is useful when we want to make the variable global
   *
   */
  public function initializeVariable($appendable=false)
  {
    return StringUtil::appendableString('var '. $this->var.' = null',$appendable);
  }
	
  public function initialize($initialize=true,$appendable=false)
  {
    $html = '';
  	
    if($initialize)
  	  $html = 'var '. $this->var." = ";
  	  

  	$container = ($this->opt_container)? $this->opt_container : 'null';
  	$moduleId = ($this->opt_moduleId)? $this->opt_moduleId : '__MODULE_ID__';
  	$defaultTab = ($this->opt_defaultTab)? $this->opt_defaultTab : 'null';
  	$html .= "new gadgets.TabSet($moduleId, $defaultTab, $container)";

  	
  	$this->initizalized = true;
    OSConfig::importTabs();
    
  	return StringUtil::appendableString($html,$appendable);
  }

  public function initialized()
  {
    return $this->initizalized;
  }
  
  /**
   * Throws sfException if it's not initialized
   * @throws sfException If it's not initialized
   */
  private function assertInitialized()
  {
    if(!$this->initialized())
  	  throw new sfException('Must call method initialize before use this method');
  }
  
  /**
   * Adds a new tab based on the name-value pairs specified in opt_params.
   * @param boolean $jsTabName This should be set to true if the tabs name should be handled as a JavaScript variable
   * @return string HTML string
   */
  public function addTab(GadgetsTab $tab,$jsTabName=false)
  {
  	$this->assertInitialized();
  	
  	$html = $tab->getParams();
  	$html.= $this->getVarName().'.addTab(';
  	
  	if($jsTabName)
  	  $html.= $tab->getName();
  	else
  	  $html.= '"'.$tab->getName().'"';
  	  
  	$html.= ', '.$tab->getParamsVar().')';
  	return StringUtil::appendableString($html,false);
  }
  
  /**
   * Returns the currently selected tab object. 
   *
   * @return GadgetsTab Returns the currently selected tab object. 
   */
  public function getSelectedTab($initialize=true,$appendable=false)
  {
    $this->assertInitialized();
  	  
    $tab = new GadgetsTab('tab',true);
    if($initialize)
  	  echo StringUtil::appendableString('var '.$tab->getVarName().' = '.$this->var.'.getSelectedTab()',$appendable);
  	return $tab;
  }
  
  /**
   * Sets the alignment of tabs. Tabs are center-aligned by default.
   *
   * @param string $align
   * @param integer $opt_offset
   */
  public function alignTabs($align, $opt_offset=null,$appendable=false)
  {
    $this->assertInitialized();
    $html = $this->getVarName().".alignTabs($align";
    if($opt_offset)
      if(is_integer($opt_offset))
        $html .= ",$opt_offset";
      else 
        throw new sfException("The offset must be integer. Given '$opt_offset'");
    
    return StringUtil::appendableString("$html)",$appendable);
  }
  
  /**
   * Sets the alignment of tabs to ALIGN_LEFT
   *
   * @param integer $opt_offset
   */
  public function alignTabsLeft($opt_offset=null,$appendable=false)
  {
    return $this->alignTabs(GadgetsTabSet::ALIGN_LEFT,$opt_offset,$appendable);
  }
  
  /**
   * Sets the alignment of tabs to ALIGN_RIGHT
   *
   * @param integer $opt_offset
   */
  public function alignTabsRight($opt_offset=null,$appendable=false)
  {
    return $this->alignTabs(GadgetsTabSet::ALIGN_RIGHT,$opt_offset,$appendable);
  }
  
  /**
   * Sets the alignment of tabs to ALIGN_CENTER
   *
   * @param integer $opt_offset
   */
  public function alignTabsCenter($opt_offset=null,$appendable=false)
  {
    return $this->alignTabs(GadgetsTabSet::ALIGN_CENTER,$opt_offset,$appendable);
  }
  
  /**
   * Shows or hides tabs and all associated content. 
   * 
   * @param boolean $display true to show tabs; false to hide tabs.
   */
  public function displayTabs($display=null)
  {
    $this->assertInitialized();
    
    $html = $this->getVarName().".displayTabs(";
    if(is_null($display))
      $html.= 'true';
    else if(is_bool($display)){
      if($display)
        $html.= 'true';
      else
        $html.= 'false';
    }else if(is_string($display))
      $html.= $display;
    else
      throw new sfException("The display must be boolean. Given '$display'");
      
    return StringUtil::appendableString($html.')',false);
  }
  
  /**
   * This method is meant to be used inside a for loop. To use this method you should do something like this inside a javascript function in the view:
   * <code>
   *  for(<?php $tab = $tabset->getEachTab(); ?>){
   * 	<?php echo $tab->getTabName(); ?>
   * </code>
   * This method will generate the necessary content for the for loop and will return an GadgetsTab object that you can use inside the for loop. 
   * This method can only be used in the view, since it echoes the for loop content to it.
   * @param integer $tabs_length This value is useful when removing all tabs
   * @return GadgetsTab 
   */
  public function getEachTab($start_idx=0,$tabs_length=null,$inc_idx=true)
  {
    $this->assertInitialized();
    $tab_idx = $this->getVarName().'_IDX';
    $tabs_array = $this->getVarName().'.getTabs()';
    if(!$tabs_length)
      $tabs_length = "$tabs_array.length";
    if($inc_idx)
      $inc_idx = "$tab_idx++";
    else
      $inc_idx='';
    
    $html = "$tab_idx=$start_idx;$tab_idx<$tabs_length;$inc_idx";
    echo $html;
    
    $tab = new GadgetsTab($tabs_array.'['.$tab_idx.']',true);

    return $tab;
  }
  
  /**
   * Removes a tab at tabIndex and all of its associated content.
   *
   * @param Integer $tabIndex 
   * @return HTML string
   */
  public function removeTabByIndex($tabIndex)
  {
    $this->assertInitialized();
    $html = $this->getVarName().".removeTab($tabIndex)";
    return StringUtil::appendableString($html,false);
  }
  
  /**
   * Removes a tab and all of its associated content.
   *
   * @param Integer $tabIndex 
   * @return HTML string
   */
  public function removeTab(GadgetsTab $tab)
  {
    return $this->removeTabByIndex($tab->getTabIndex(true));
  }
  
  /**
   * Returns the tab headers container element.
   *
   * @param unknown_type $appendable
   * @return Returns the tab headers container element.
   */
  public function getHeaderContainer($appendable=false)
  {
    $this->assertInitialized();
    $html = $this->getVarName().".getHeaderContainer()";
    return StringUtil::appendableString($html,$appendable);
  }
  
  /**
   * Selects the tab at tabIndex and fires the tab's callback function if it exists. If the tab is already selected, the callback is not fired.
   *
   * @param unknown_type $tabIndex
   * @return unknown
   */
  public function setSelectedTabByIndex($tabIndex)
  {
    $this->assertInitialized();
    $html = $this->getVarName().".setSelectedTab($tabIndex)";
    return StringUtil::appendableString($html,false);
  }
  
  /**
   * Selects the tab and fires the tab's callback function if it exists. If the tab is already selected, the callback is not fired.
   *
   * @param unknown_type $tabIndex
   * @return unknown
   */
  public function setSelectedTab(GadgetsTab $tab)
  {
    return $this->setSelectedTabByIndex($tab->getTabIndex(true));
  }

  public function swapTabsByIndex($tabIndex1,$tabIndex2)
  {
    $this->assertInitialized();
    $html = $this->getVarName().".swapTabs($tabIndex1,$tabIndex2)";
    return StringUtil::appendableString($html,false);
  }
      
}